#!/usr/bin/env python
##-----------------------------------------------------------------------------
##  File:   tex_iter.py
##  Author: Jim Storch
##-----------------------------------------------------------------------------

import re
import sys

def tex_iter(filename):

    """
    Iterator for LaTeX source files.

    Given a LaTeX source file name, iterates through each line of the file
    returning a tuple containing the filename, the current line number, and
    the text of the line with comments stripped.

    If it encounters a line with a "\include" or "\input", it recursively 
    iterates the nested file instead of returning the line.
    """

    ## Regex to match comments
    re_comment = r"""([^\\]|^)\%.*$"""

    ## Regex to match include files
    re_include = r"""\\include\{(?P<filename>.[^}]+)\}"""
    
    ## Regex to match input files
    re_input = r"""\\input\{(?P<filename>.[^}]+)\}"""

    try:
        fp = open(filename, 'r')
        try:
            ## Loop through the open file
            for number, line in enumerate(fp):

                ## Strip any comments
                line = re.sub(re_comment, '', line.strip())
        
                ## Look for nested tex files
                include_file = re.search(re_include, line)
                input_file = re.search(re_input, line)
    
                ## Include file - dive in!
                if include_file:
                    nested = include_file.group('filename')
                    for tup in tex_iter(nested):
                        yield tup
                
                ## Input file - dive in!
                elif input_file:
                    nested = input_file.group('filename')
                    for tup in tex_iter(nested):
                        yield tup
                
                ## Nothing special, yield and repeat
                else:
                    yield(filename, number, line)
        finally:
            fp.close()
    except IOError:
        print ('ERROR! Missing file: %s') % (filename)
        sys.exit(1)

